package net.mof.manual.meta

import com.squareup.javapoet.ClassName
import com.squareup.javapoet.CodeBlock
import com.squareup.javapoet.ParameterizedTypeName
import com.squareup.javapoet.TypeName
import net.mof.manual.MarkedClassInfo
import net.mof.manual.Utils.arrayListClassName
import net.mof.manual.Utils.jsonArrayClassName
import net.mof.manual.Utils.jsonObject
import net.mof.manual.Utils.listClassName
import net.mof.manual.Utils.manualClassName
import net.mof.manual.Utils.stringClassName
import net.mof.manual.Utils.upFirstChar
import javax.lang.model.type.TypeMirror

/**
 *
 * list类型
 *
 * Created by LiYueHui on 2020/2/2.
 */
class ListFieldMetaInfo : BaseFieldMetaInfo() {
    var typeParamTypeMirror: TypeMirror? = null

    override fun optField(): String = "JSONArray"

    override fun instanceTypeName(): TypeName = jsonArrayClassName

    override fun jsonToTypeGet(builder: CodeBlock.Builder, markedClassInfo: MarkedClassInfo) {
        // ParameterizedTypeName list = ParameterizedTypeName.get(listClassName,
// TypeName.get(typeParamTypeMirror));
        val arrayList = ParameterizedTypeName.get(
                arrayListClassName, TypeName.get(typeParamTypeMirror))

        builder.beginControlFlow("if (\$L != null && \$L.length() > 0)", value,
                value)
                .addStatement("\$T \$L = new \$T()", arrayList, value + "list",
                        arrayList)
                .beginControlFlow("for(int i = 0; i < \$L.length(); i++)", value)
        if ("JSONObject" == opt()) {
            builder.addStatement(
                    "\$L.add(\$T.jsonToType(\$L.opt\$L(i).toString(),\$T.class))",
                    value + "list", manualClassName, value, opt(),
                    TypeName.get(typeParamTypeMirror))
        } else {
            builder.addStatement("\$L.add(\$L.opt\$L(i))", value + "list", value,
                    opt())
        }
        builder.endControlFlow()
                .addStatement("\$L.set\$L(\$L)",
                        markedClassInfo.getFileName()?.toLowerCase(),
                        upFirstChar(filedName()), value + "list").endControlFlow()
    }

    override fun typeToJsonObjectPut(builder: CodeBlock.Builder?, param: String?) {
        val list = ParameterizedTypeName.get(listClassName,
                TypeName.get(typeParamTypeMirror))
        builder!!.addStatement("\$T \$L = new \$T()", jsonArrayClassName, value
                + "array", jsonArrayClassName)
        builder.addStatement("\$T \$L = \$L.get\$L()", list, value, param,
                upFirstChar(filedName()))
        builder.beginControlFlow("if(\$L != null)", value)
        builder.beginControlFlow("for(int i = 0;i < \$L.size();i++)", value)
        if ("JSONObject" == opt()) {
            builder.addStatement("\$L.put((\$T.typeToJSONObject(\$L.get(i))))",
                    value + "array", manualClassName, value)
        } else {
            builder.addStatement("\$L.put(\$L.get(i))", value + "array", value)
        }
        builder.endControlFlow()
        builder.addStatement("\$L.put(\$S,\$L)", jsonObject, value, value
                + "array")
        builder.endControlFlow()
    }

    private fun opt(): String? {
        val typeName = TypeName.get(typeParamTypeMirror)
        if (stringClassName == typeName) {
            return "String"
        } else if (typeName.isBoxedPrimitive) {
            if (ClassName.INT.box() == typeName) {
                return "Int"
            } else if (ClassName.LONG.box() == typeName) {
                return "Long"
            } else if (ClassName.BOOLEAN.box() == typeName) {
                return "Boolean"
            } else if (ClassName.FLOAT.box() == typeName) {
                return "Float"
            } else if (ClassName.DOUBLE.box() == typeName) {
                return "Double"
            }
        } else {
            return "JSONObject"
        }
        return null
    }

}